package cn.yotta.user.core.server.manager.user;

import cn.yotta.common.api.model.Paging;
import cn.yotta.user.api.params.user.UserPageRequest;
import cn.yotta.user.core.server.converter.PageConvert;
import cn.yotta.user.core.server.converter.UserConverter;
import cn.yotta.user.core.server.dao.UserDao;
import cn.yotta.user.core.server.dto.user.UserDto;
import cn.yotta.user.core.server.entity.User;
import cn.yotta.user.core.server.event.UserStatusChangeEventListener;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import static cn.yotta.user.core.server.event.UserStatusChangeEventListener.EventType.*;

/**
 * @author wyaoyao
 * @date 2022/11/8 18:19
 */
@Service
@Slf4j
public class UserManagerImpl implements UserManager {

    private final UserConverter userConverter;

    private final ApplicationEventPublisher applicationEventPublisher;

    private final UserDao userDao;

    public UserManagerImpl(UserConverter userConverter,
                           ApplicationEventPublisher applicationEventPublisher, UserDao userDao) {
        this.userConverter = userConverter;
        this.applicationEventPublisher = applicationEventPublisher;
        this.userDao = userDao;
    }

    @Override
    public List<UserDto> findUserByIds(Long tenantId, Collection<Long> ids) {
        List<User> userByIds = this.userDao.findUserByIds(tenantId, ids);
        return userByIds.stream().map(this.userConverter::model2Dto).collect(Collectors.toList());
    }

    @Override
    public UserDto findUserById(Long tenantId, Long id) {
        User userById = this.userDao.findUserById(tenantId, id);
        return this.userConverter.model2Dto(userById);
    }

    @Override
    public UserDto findByUsername(Long tenantId, String username) {
        User byUsername = this.userDao.findByUsername(tenantId, username);
        return this.userConverter.model2Dto(byUsername);
    }

    @Override
    public Paging<UserDto> page(UserPageRequest pageRequest) {
        return this.page(pageRequest.getPageNo()
                , pageRequest.getPageSize(),
                this.userConverter.toModel(pageRequest));
    }

    @Override
    public Boolean freezeUser(Long tenantId, Long id, Long operatorId) {
        Boolean isSuccess = this.userDao.freezeUser(tenantId, id, operatorId);
        if (isSuccess) {
            // 发布用户冻结事件
            applicationEventPublisher.publishEvent(new UserStatusChangeEventListener.UserStatusChangeEvent(id, USER_FREEZE));
        }
        return isSuccess;
    }

    @Override
    public Boolean unFreeze(Long tenantId, Long id, Long operatorId) {
        Boolean isSuccess = this.userDao.unFreeze(tenantId, id, operatorId);
        // 发布用户解冻结事件
        if (isSuccess) {
            applicationEventPublisher.publishEvent(new UserStatusChangeEventListener.UserStatusChangeEvent(id, USER_UNFREEZE));
        }
        return isSuccess;
    }

    @Override
    public Boolean enable(Long tenantId, Long id, Long operatorId) {
        Boolean isSuccess = this.userDao.enable(tenantId, id, operatorId);
        if (isSuccess) {
            // 发布用户启用事件
            applicationEventPublisher.publishEvent(new UserStatusChangeEventListener.UserStatusChangeEvent(id, USER_ENABLE));
        }
        return isSuccess;
    }

    @Override
    public Boolean disable(Long tenantId, Long id, Long operatorId) {
        Boolean isSuccess = this.userDao.disable(tenantId, id, operatorId);
        if (isSuccess) {
            // 发布用户禁用事件
            applicationEventPublisher.publishEvent(new UserStatusChangeEventListener.UserStatusChangeEvent(id, USER_DISABLE));
        }
        return isSuccess;
    }

    @Override
    public UserDto findUserByMobile(Long tenantId, String mobile) {
        User user = this.userDao.findUserByMobile(tenantId, mobile);
        return this.userConverter.model2Dto(user);
    }

    private Paging<UserDto> page(Integer pageNo, Integer pageSize, User user) {
        final Page<User> pageResult = this.userDao.page(pageNo, pageSize, user);
        return PageConvert.convert(pageResult, this.userConverter::model2Dto);
    }


}
